package com.deparse.dpframe.ui.fragment;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.deparse.dpframe.bean.DPView;
import com.deparse.dpframe.common.DPBusEvent;
import com.deparse.dpframe.common.DPBusEventCommands;
import com.deparse.dpframe.common.DPConsts;
import com.deparse.dpframe.ui.activity.DPBaseActivity;
import com.deparse.dpframe.ui.interfaces.IDPBaseFragment;
import com.deparse.dpframe.utils.DPLogUtil;

import org.simple.eventbus.EventBus;
import org.simple.eventbus.Subscriber;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Created by MartinDKent on 2016/1/16.
 */
public abstract class DPBaseFragment extends Fragment implements IDPBaseFragment {
    private RelativeLayout rootViewContainer;

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            onHandleMessage(msg);
        }
    };

    private Map<Integer, DPView> cacher = new HashMap<>(20);

    private View rootView = null;
    private DPBaseActivity activity;

    public void setAttchedActivity(DPBaseActivity activity) {
        this.activity = activity;
    }

    public DPBaseActivity getAttchedActivity() {
        return activity;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        this.activity = (DPBaseActivity) activity;
    }

    @Override
    public void customExt(String tag, Object... args) {

    }

    /**
     * findViewById
     *
     * @param resId
     * @return
     */
    public <T extends View> T findViewById(int resId) {
        return rootView == null ? null : (T) rootView.findViewById(resId);
    }

    /**
     * F
     *
     * @param resId
     * @param <T>
     * @return
     */
    protected <T> T F(int resId) {
        return null == findViewById(resId) ? null : (T) findViewById(resId);
    }

    /**
     * $
     *
     * @param resId
     * @return
     */
    protected DPView $(int resId) {
        if (null == cacher.get(resId)) {
            cacher.put(resId, new DPView(F(resId)));
        }
        return cacher.get(resId);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EventBus.getDefault().register(this);
    }

    @Override
    public void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }

    @Subscriber(tag = "onEventMainThread")
    public void onEventMainThread(DPBusEvent event) {

    }

    /**
     * postBusEvent
     *
     * @param event
     */
    public void postBusEvent(DPBusEvent event) {
        EventBus.getDefault().post(event, "onEventMainThread");
    }

    /**
     * postBusEventDelayed
     *
     * @param event
     * @param duration
     */
    public void postBusEventDelayed(final DPBusEvent event, final int duration) {
        postDelayed(new Runnable() {
            @Override
            public void run() {
                postBusEvent(event);
            }
        }, duration);
    }

    /**
     * finishAllActivities
     */
    protected void finishAllActivities() {
        DPBusEvent DPBusEvent = new DPBusEvent();
        DPBusEvent.what = DPBusEventCommands.EVENT_FINISH_ACTIVITY;
        DPBusEvent.args = new int[]{DPBusEventCommands.EVENT_CONFIRM_FINISH_ACTIVITY};
        postBusEvent(DPBusEvent);
    }

    /**
     * onCreateView
     *
     * @param inflater
     * @param container
     * @param savedInstanceState
     * @return
     */
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (0 != getFragmentLayout()) {
            rootView = inflater.inflate(getFragmentLayout(), null);
            rootViewContainer = new RelativeLayout(getContext());
            rootViewContainer.addView(rootView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            return rootViewContainer;
        }
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    /**
     * onViewCreated
     *
     * @param view
     * @param savedInstanceState
     */
    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initView(view, savedInstanceState);
        AsyncTask task = new AsyncTask() {
            @Override
            protected Object doInBackground(Object[] params) {
                initData();
                return null;
            }
        };
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    /**
     * getRootView
     *
     * @return
     */
    @Override
    public View getRootView() {
        return rootView;
    }

    protected void removeMessages(int what) {
        mHandler.removeMessages(what);
    }

    protected void removeMessages(int what, Object obj) {
        mHandler.removeMessages(what, obj);
    }

    protected void removeCallbacks(Runnable r) {
        mHandler.removeCallbacks(r);
    }

    protected void removeCallbacks(Runnable r, Object token) {
        mHandler.removeCallbacks(r, token);
    }

    protected void removeCallbacksAndMessages(Object token) {
        mHandler.removeCallbacksAndMessages(token);
    }

    /**
     * sendEmptyMessage
     *
     * @param what
     */
    protected void sendEmptyMessage(int what) {
        mHandler.sendEmptyMessage(what);
    }

    /**
     * sendEmptyMessage
     *
     * @param what
     * @param delay
     */
    protected void sendEmptyMessageDelayed(int what, int delay) {
        mHandler.sendEmptyMessageDelayed(what, delay);
    }

    /**
     * sendMessage
     *
     * @param msg
     */
    protected void sendMessage(Message msg) {
        mHandler.sendMessage(msg);
    }

    /**
     * sendMessageDelayed
     *
     * @param msg
     * @param delay
     */
    protected void sendMessageDelayed(Message msg, int delay) {
        mHandler.sendMessageDelayed(msg, delay);
    }

    /**
     * post
     *
     * @param runnable
     */
    protected void post(Runnable runnable) {
        mHandler.post(runnable);
    }

    /**
     * postDelayed
     *
     * @param runnable
     * @param delay
     */
    protected void postDelayed(Runnable runnable, int delay) {
        mHandler.postDelayed(runnable, delay);
    }

    /**
     * postAtFrontOfQueue
     *
     * @param runnable
     */
    protected void postAtFrontOfQueue(Runnable runnable) {
        mHandler.postAtFrontOfQueue(runnable);
    }

    /**
     * getFragmentLayout
     *
     * @return
     */
    protected abstract int getFragmentLayout();

    /**
     * initView
     *
     * @param view
     * @param savedInstanceState run in UI thread
     */
    protected abstract void initView(View view, Bundle savedInstanceState);

    /**
     * initData
     * run int background with AsyncTask.
     */
    protected abstract void initData();

    /**
     * onHandleMessage.
     *
     * @param msg called when a message be handled
     */
    protected abstract void onHandleMessage(Message msg);

    /**
     * isEmpty
     *
     * @param src
     * @return
     */
    protected static boolean isEmpty(String src) {
        return null == src || "".equals(src);
    }

    /**
     * isEmpty
     *
     * @param src
     * @param <T>
     * @return
     */
    protected static <T> boolean isEmpty(T[] src) {
        return null == src || 0 == src.length;
    }

    /**
     * isEmpty
     *
     * @param src
     * @return
     */
    protected static boolean isEmpty(List<?> src) {
        return null == src || 0 == src.size();
    }

    /**
     * isEmpty
     *
     * @param src
     * @return
     */
    protected static boolean isEmpty(Map<?, ?> src) {
        return null == src || 0 == src.size();
    }

    private Toast toast = null;

    /**
     * showToast
     *
     * @param resId
     * @param dependency
     */
    public void showToast(int resId, Boolean... dependency) {
        showToast(getString(resId), dependency);
    }

    /**
     * showToast
     *
     * @param msg
     * @param dependency
     */
    public void showToast(String msg, Boolean... dependency) {
        if (!isEmpty(dependency) && true == dependency[0]) {
            Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show();
        }
        if (null == toast) {
            toast = Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT);
        } else {
            toast.setText(msg);
        }
        toast.show();
    }

    /**
     * startActivity
     *
     * @param cls
     * @param extras
     */
    public void startActivity(Class<?> cls, String... extras) {
        Intent intent = new Intent(getAttchedActivity(), cls);
        intent.putExtra(DPConsts.ACTIVITY_START_STRING_EXTRAS, extras);
        super.startActivity(intent);
    }

    /**
     * startActivity
     *
     * @param cls
     * @param extras
     */
    public void startActivityWithTaskCleared(Class<?> cls, String... extras) {
        Intent intent = new Intent(getAttchedActivity(), cls);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(DPConsts.ACTIVITY_START_STRING_EXTRAS, extras);
        super.startActivity(intent);
    }

    /**
     * startActivityForResult
     *
     * @param cls
     * @param requestCode
     * @param data
     */
    public void startActivityForResult(Class<?> cls, int requestCode, String... data) {
        Intent intent = new Intent(getAttchedActivity(), cls);
        intent.putExtra(DPConsts.ACTIVITY_START_STRING_EXTRAS, data);
        super.startActivityForResult(intent, requestCode);
    }

    public void addContentView(View view, ViewGroup.LayoutParams params) {
        rootViewContainer.addView(view, params);
    }

    public void addContentView(View view, int index, ViewGroup.LayoutParams params) {
        rootViewContainer.addView(view, index, params);
    }
}
